<template>
  <div class="page page-screenshare-webrtc-client">
    <h4 class="text-center">接收端演示窗口（WebRTC）</h4>
    <form class="page-body row">
      <div class="col-4">
        <fieldset>
          <legend>操作</legend>
          <div class="fieldset-content">
            <div class="form-group row-flex">
                <div class="row-flex-prefix">服务端IP</div>
                <div class="row-flex-main">
                  <div class="input-group">
                    <input type="text" class="form-control" v-model.trim="serverIP" placeholder="请输入服务端IP">
                    <div class="input-group-append" @click="listenWebrtcServer">
                      <span class="input-group-text">连接</span>
                    </div>
                  </div>
                </div>
            </div>
            <div class="form-group">
              <x-button block @click="join">加入直播间</x-button>
              <x-button block @click="leave">退出直播间</x-button>
            </div>
          </div>
        </fieldset>
      </div>
      <div class="col-8">
        <fieldset>
          <legend>直播画面</legend>
          <div class="fieldset-content">
            <video ref="video" autoplay="autoplay"></video>
          </div>
        </fieldset>
      </div>
    </form>
  </div>
</template>

<script>
import io from 'socket.io-client'

export default {
  name: 'page-screenshare-webrtc-client',
  data () {
    return {
      serverIP: '',
      wsWaiter: null,
      peerConnection: null,
    }
  },
  methods: {
    // 连接webrtc websocket服务器
    listenWebrtcServer () {
      if (this.wsWaiter) { this.wsWaiter.close() }
      this.serverIP = this.serverIP || '127.0.0.1'
      this.wsWaiter = io.connect(`http://${this.serverIP}:7650/clients`)
      this.wsWaiter.on('resetConnection', (res) => {
        console.log('resetConnection:', res)
        this.leave()
        this.join()
      })
      this.wsWaiter.on('canJoin', (res) => {
        console.log('canJoin:', res)
        this.createPeerConnection()
      })
      this.wsWaiter.on('remoteCandidate', (res) => {
        console.log('remoteCandidate:', res)
        let {data} = res || {}
        if (!this.peerConnection || !data) return
        this.peerConnection.addIceCandidate(data)
      })
      this.wsWaiter.on('remoteDescription', (res) => {
        console.log('remoteDescription:', res)
        let {data} = res || {}
        if (!this.peerConnection || !data) return
        this.peerConnection.setRemoteDescription(data)
        this.createAnswer()
      })
      this.wsWaiter.on('closeConnection', (res) => {
        console.log('closeConnection:', res)
        if (!this.peerConnection) return
        this.peerConnection.close()
        this.peerConnection = null
        this.loadStream(null)
        this.$toast('直播间关闭了')
      })
    },
    createAnswer () {
      if (!this.peerConnection) return
      this.peerConnection.createAnswer().then((data) => {
        this.peerConnection.setLocalDescription(data)
        this.wsWaiter && this.wsWaiter.emit('description', data)
      }).catch((err) => {
        console.error('createAnswer:', err)
        this.$toast('createAnswer 时发生错误')
      })
    },
    createPeerConnection () {
      this.peerConnection = new RTCPeerConnection()
      this.peerConnection.onicecandidate = (e) => {
        console.log('onicecandidate:', e)
        if (!e.candidate) return
        this.wsWaiter && this.wsWaiter.emit('candidate', e.candidate)
      }
      // 获取远程视频
      this.peerConnection.ontrack = (e) => {
        this.loadStream(e.streams[0])
      }
    },
    // 加载视频流
    loadStream (stream) {
      if (!this.$refs.video) return
      try {
        this.$refs.video.srcObject = stream
      } catch (err) {
        this.$refs.video.src = window.URL.createObjectURL(stream)
      }
    },
    join () {
      this.wsWaiter && this.wsWaiter.emit('join')
    },
    leave () {
      if (this.peerConnection) {
        this.peerConnection.close()
        this.peerConnection = null
        this.loadStream(null)
      }
      this.wsWaiter && this.wsWaiter.emit('leave')
    },
  }
}
</script>

<style scoped lang="less">
@import "~@/assets/css/_mixins.less";
@import "~@/assets/css/_color.less";
@gapSize: 10px;

.page-screenshare-webrtc-client {
  display: flex;
  flex-direction: column;
  .page-body {
    height: 0;
    flex-grow: 1;
    fieldset {
      height: 100%;
      .fieldset-content {
        height: calc(100% - 2em);
        video {
          width: 100%;
          height: 100%;
          object-fit: contain;
          background-color: #333;
        }
      }
      .x-button {
        margin-bottom: @gapSize;
      }
    }
  }
}
</style>
